package cn.hacynn.nd.service.impl;

import cn.hacynn.nd.common.constant.MessageConstant;
import cn.hacynn.nd.common.context.BaseContext;
import cn.hacynn.nd.common.exception.SafeFileException;
import cn.hacynn.nd.common.properties.RedisProperties;
import cn.hacynn.nd.common.utils.RedisUtils;
import cn.hacynn.nd.mapper.FileMapper;
import cn.hacynn.nd.mapper.SafeFileMapper;
import cn.hacynn.nd.mapper.UserMapper;
import cn.hacynn.nd.pojo.entity.File;
import cn.hacynn.nd.pojo.entity.SafeFile;
import cn.hacynn.nd.pojo.entity.User;
import cn.hacynn.nd.service.FileService;
import cn.hacynn.nd.service.SafeFileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.util.List;
import java.util.TimeZone;

/**
 * @Author Hacynn
 * @Date 2024/5/27 23:13
 * @Version 1.0
 */
@Service
@Slf4j
public class SafeFileServiceImpl implements SafeFileService {

    public static final String SAFE_PERMIT = "SAFE-";

    @Autowired
    private SafeFileMapper safeFileMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private RedisProperties redisProperties;
    @Autowired
    private FileMapper fileMapper;
    @Autowired
    private FileService fileService;


    /**
     * 查询是否激活保险箱
     * @return
     */
    @Override
    public Boolean check() {
        //查询用户id
        Long userId = BaseContext.getCurrentId();
        //查询用户信息
        User user = userMapper.selectById(userId);
        // 返回用户信息中的是否激活保险箱字段
        return user.getIsSafeOn();
    }

    /**
     * 查询是否进入过保险箱
     * @return
     */
    @Override
    public Boolean checkEntered() {
        //查询用户信息
        Long userId = BaseContext.getCurrentId();
        User user = userMapper.selectById(userId);
        // 从 redis 中查询是否存在用户对应的键
        return redisUtils.hasKey(SAFE_PERMIT + user.getEmail());
    }

    /**
     * 激活保险箱
     * @param safeCode
     */
    @Override
    public void activate(String safeCode) {    // TODO 保险箱密钥需要加密存储
        // TODO 还需要判断字母+数组且大于6小于18
        if (!StringUtils.hasLength(safeCode)) {
            // 密钥为空
            throw new SafeFileException(MessageConstant.SAFE_CODE_IS_NULL);
        }
        // 查询用户信息
        Long userId = BaseContext.getCurrentId();
        User user = User.builder()
                .id(userId)
                .isSafeOn(true)
                .safeCode(safeCode)
                .build();
        //更新用户激活保险箱
        userMapper.updateById(user);
    }

    /**
     * 校验保险箱密钥
     * @param safeCode
     * @return
     */
    @Override
    public Boolean match(String safeCode) {
        if (!StringUtils.hasLength(safeCode)) {
            // 密钥为空
            throw new SafeFileException(MessageConstant.SAFE_CODE_IS_NULL);
        }
        //查询用户信息
        Long userId = BaseContext.getCurrentId();
        User user = userMapper.selectById(userId);
        if (!user.getIsSafeOn()) {
            // 未激活保险箱
            throw new SafeFileException(MessageConstant.SECURE_CASE_NOT_ACTIVATE);
        }
        // 校验密钥是否正确
        boolean equals = safeCode.equals(user.getSafeCode());
        // redis键名
        String key = SAFE_PERMIT + user.getEmail();
        if (equals) {
            // 密钥正确，存入redis，后续一定时间内访问保险箱无需再次输入密钥
            redisUtils.set(key, "pass", redisProperties.getSecureCaseKeyLifetime());
        }
        return equals;
    }

    /**
     * 查询保险箱中的文件列表信息
     * @return
     */
    @Override
    public List<File> list() {
        //查询用户信息
        Long userId = BaseContext.getCurrentId();
        List<File> files = fileMapper.getSafeFileByUserId(userId);
        if (files == null) {
            // 保险箱中无文件
            throw new SafeFileException(MessageConstant.SECURE_CASE_NOT_FILE);
        }
        // 根据是否为目录进行排序（目录排在前面）
        fileService.sortByDir(files);
        // 设置前端显示的格式
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM/dd HH:mm");
        simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT+8"));

        files.forEach(f -> f.setLastModified(simpleDateFormat.format(f.getUpdateTime())));
        return files;
    }

    /**
     * 锁定保险箱
     */
    @Override
    public void lockSafe() {
        //查询用户信息
        Long userId = BaseContext.getCurrentId();
        User user = userMapper.selectById(userId);
        //获取key用来下列删除时间的操作
        String key = SAFE_PERMIT + user.getEmail();
        if (redisUtils.hasKey(key)) {
            // 删除redis中用于确定超时时间的信息
            redisUtils.delete(key);
        }
    }

    /**
     * 移出保险箱
     * @param ossPath
     */
    @Override
    public void moveOutSafe(String ossPath) {
        if (ossPath == null) {
            // 文件路径为空
            throw new SafeFileException(MessageConstant.FILE_PATH_IS_NULL);
        }
        Long userId = BaseContext.getCurrentId();
        File file = fileMapper.getFileByPath(userId, ossPath);
        if (file == null) {
            // 文件不存在
            throw new SafeFileException(MessageConstant.FILE_NOT_EXIST);
        }
        if (file.getDeleted()) {
            // 文件已被移到回收站中
            throw new SafeFileException(MessageConstant.FILE_IN_RECYCLE_BIN);
        }
        // 删除SafeFile表中的数据
        safeFileMapper.deleteByFileId(userId, file.getId());
        // 将File中的in_safe字段修改为false
        file.setInSafe(false);
        fileMapper.updateById(file);   // 全部覆盖了，因此更新时间不会改变
    }


    /**
     * 移入保险箱
     * @param ossPath
     */
    @Override
    public void moveToSafe(String ossPath) {
        if (ossPath == null) {
            // 文件路径为空
            throw new SafeFileException(MessageConstant.FILE_PATH_IS_NULL);
        }
        //查询用户信息
        Long userId = BaseContext.getCurrentId();
        User user = userMapper.selectById(userId);

        if (!user.getIsSafeOn()) {
            // 保险箱未激活
            throw new SafeFileException(MessageConstant.SECURE_CASE_NOT_ACTIVATE);
        }
        //查询文件
        File file = fileMapper.getFileByPath(userId, ossPath);
        if (file == null) {
            // 文件不存在
            throw new SafeFileException(MessageConstant.FILE_NOT_EXIST);
        }
        if (file.getDeleted()) {
            // 文件已被移到回收站中
            throw new SafeFileException(MessageConstant.FILE_IN_RECYCLE_BIN);
        }
        // 删除SafeFile表中的数据
        safeFileMapper.deleteByFileId(userId, file.getId());
        // 将File中的in_safe字段修改为true
        file.setInSafe(true);
        fileMapper.updateById(file);   // 全部覆盖了，因此更新时间不会改变
        // 向SafeFile插入记录
        SafeFile safeFile = SafeFile.builder()
                .fileId(file.getId())
                .userId(user.getId())
                .build();
        safeFileMapper.insert(safeFile);
    }
}
